package com.lagou.java;

import com.lagou.java.handler.UserServiceHandler;
import com.lagou.java.service.UserService;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.string.StringEncoder;
import lombok.extern.slf4j.Slf4j;
import sun.rmi.runtime.Log;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class NettyServer {


    public static void startServer(String hostName, int port, Map<Integer, NettyServerBootstrap.ServerData> serverDatas) {
        NettyServerBootstrap.ServerData serverData = serverDatas.get(port);
        if (serverData == null || !serverData.getChannelFuture().channel().isActive()) {
            log.info("==>>服务端在端口：{}, 建立了新的服务节点", port);
            NettyServerBootstrap.ServerData data = new NettyServerBootstrap.ServerData();
            new Thread(() -> {
                Channel channel = null;
                NioEventLoopGroup bossLoopGroup = null;
                NioEventLoopGroup childLoopGroup = null;
                try {
                    bossLoopGroup = new NioEventLoopGroup();
                    childLoopGroup = new NioEventLoopGroup();
                    ServerBootstrap bootstrap = new ServerBootstrap();
                    UserServiceHandler handler = new UserServiceHandler();

                    bootstrap.group(bossLoopGroup, childLoopGroup)
                            .channel(NioServerSocketChannel.class)
                            .childHandler(new ChannelInitializer<SocketChannel>() {

                                @Override
                                protected void initChannel(SocketChannel socketChannel) throws Exception {
                                    ChannelPipeline pipeline = socketChannel.pipeline();
                                    //                            pipeline.addLast(new StringDecoder());
                                    // Netty半包解码器解决TCP粘包/拆包问题
                                    pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 2, 0, 2));
                                    // 返回结果编码码器
                                    pipeline.addLast(new StringEncoder());
                                    // 入参解码器
                                    pipeline.addLast(new RpcDecoder());
                                    // 自定义 ChannelHandler

                                    pipeline.addLast(handler);
                                }
                            });
                    // 绑定端口
                    ChannelFuture sync = bootstrap.bind(hostName, port).sync();
                    channel = sync.channel();
                    // 保存运行时变量到本地缓存
                    data.setServerBootstrap(bootstrap);
                    data.setChannelFuture(sync);
                    data.setHandler(handler);
                    data.setBossGroup(bossLoopGroup);
                    data.setWorkerGroup(childLoopGroup);

                    sync.addListener(new ChannelFutureListener() {
                        @Override
                        public void operationComplete(ChannelFuture future) throws Exception {
                            if (future.isSuccess()) {
                                log.info("========>>>>> netty server started at " + hostName + ":" + port);
                                // 将节点信息注册到 zookeeper
                                String address = future.channel().localAddress().toString().substring(1);
                                ZkBoostrap<UserService> zkBoostrap = new ZkBoostrap<>();
                                String node = zkBoostrap.addNode(address);
                                data.setNode(node);
                            } else {
                                log.info("========>>>>> netty server started failed ");
                            }
                        }
                    });

                    ChannelFuture channelFuture = channel.closeFuture().sync();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    log.info("服务在端口：{} 结束运行", port);
                    NettyServerBootstrap.ServerData dataR = NettyServerBootstrap.servers.get(port);
                    String node = dataR.getNode();
                    try {
                        new ZkBoostrap<UserServiceHandler>().delete(node);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    NettyServerBootstrap.servers.remove(port);

                    // 服务端优雅关闭
                    bossLoopGroup.shutdownGracefully();
                    childLoopGroup.shutdownGracefully();

                }
            }).start();
            serverDatas.put(port, data);
        } else {
            log.info("===>> 端口：{}, 已经有服务在运行， 无需创建", port);
        }
    }


}
